// Create a new file: src/storage/database.ts

import * as fs from "fs";
import * as path from "path";
import * as vscode from "vscode";
import { Logger, LogLevel } from "../infrastructure/logger/logger";

export interface IStorage {
  get<T>(key: string): Promise<T | undefined>;
  set<T>(key: string, value: T): Promise<void>;
  delete(key: string): Promise<void>;
  has(key: string): Promise<boolean>;
}

export class FileStorage implements IStorage {
  private storagePath = "";
  private readonly logger: Logger;

  constructor() {
    this.createCodeBuddyFolder();
    this.logger = Logger.initialize(FileStorage.name, {
      minLevel: LogLevel.DEBUG,
    });
  }

  async createCodeBuddyFolder() {
    const workSpaceRoot =
      vscode.workspace.workspaceFolders?.[0]?.uri.fsPath ?? "";
    this.storagePath = path.join(workSpaceRoot, ".codebuddy");
    if (!fs.existsSync(this.storagePath)) {
      fs.mkdirSync(this.storagePath, { recursive: true });
    }
    await this.updateGitIgnore(workSpaceRoot, ".codebuddy");
  }

  /**
   * Updates or creates a .gitignore file with the specified pattern
   * @param workspaceRoot The root folder of the current workspace
   * @param pattern The pattern to add to .gitignore (e.g., '.codebuddy')
   */
  async updateGitIgnore(workspaceRoot: string, pattern: string): Promise<void> {
    const gitIgnorePath = path.join(workspaceRoot, ".gitignore");

    if (fs.existsSync(gitIgnorePath)) {
      const gitIgnoreContent = fs.readFileSync(gitIgnorePath, "utf8");
      const lines = gitIgnoreContent.split(/\r?\n/);

      const patternExists = lines.some(
        (line) =>
          line.trim() === pattern ||
          line.trim() === `/${pattern}` ||
          line.trim() === `${pattern}/`,
      );

      if (!patternExists) {
        const newContent = gitIgnoreContent.endsWith("\n")
          ? `${gitIgnoreContent}${pattern}\n`
          : `${gitIgnoreContent}\n${pattern}\n`;

        fs.writeFileSync(gitIgnorePath, newContent, "utf8");
        this.logger.info(`Added ${pattern} to .gitignore`);
      }
    } else {
      fs.writeFileSync(
        gitIgnorePath,
        `# Generated by CodeBuddy Extension\n${pattern}\n`,
        "utf8",
      );
      this.logger.info(`Created new .gitignore with ${pattern}`);
    }
  }
  private getFilePath(key: string): string {
    return path.join(this.storagePath, `${key}.json`);
  }

  async get<T>(key: string): Promise<T | undefined> {
    try {
      const filePath = this.getFilePath(key);
      if (!fs.existsSync(filePath)) {
        return undefined;
      }
      const data = await fs.promises.readFile(filePath, "utf-8");
      return JSON.parse(data) as T;
    } catch (error: any) {
      this.logger.error(`Error reading data for key ${key}:`, error);
      return undefined;
    }
  }

  async set<T>(key: string, value: T): Promise<void> {
    try {
      const filePath = this.getFilePath(key);
      await fs.promises.writeFile(
        filePath,
        JSON.stringify(value, null, 2),
        "utf-8",
      );
    } catch (error: any) {
      this.logger.error(`Error storing data for key ${key}:`, error);
      throw new Error(`Failed to store data: ${error}`);
    }
  }

  async delete(key: string): Promise<void> {
    try {
      const filePath = this.getFilePath(key);
      if (fs.existsSync(filePath)) {
        await fs.promises.unlink(filePath);
      }
    } catch (error: any) {
      this.logger.error(`Error deleting data for key ${key}:`, error);
    }
  }

  async has(key: string): Promise<boolean> {
    const filePath = this.getFilePath(key);
    return fs.existsSync(filePath);
  }
}
